//based on https://dresdenlabs.appspot.com/RecentCubes.js
var diffTreeDate2=1382375462010;
var diffTree2={218036:{m:1,c:[424002,0,421008,0,0,0,0,0]},
216033:{m:1,c:[419012,416009,411012,415011,423011,424005,415012,415013]},
222039:{m:1,c:[416010,417014,416011,411013,415014,424109,420007,418109]},
409137:{m:1,c:[416139,0,419147,0,0,0,0,0]},
409138:{m:1,c:[410122,0,412125,0,0,0,0,0]},
418127:{m:1,c:[420130,0,410123,0,0,0,0,0]},
421105:{m:1,c:[432001,0,431001,0,0,0,0,0]},
423103:{m:1,c:[430001,0,427002,0,0,0,0,0]},
415140:{m:1,c:[416141,410129,411143,425114,429001,0,409146,0]},
409118:{m:1,c:[419148,424139,416140,413135,418131,0,425113,0]},
424090:{m:1,c:[423086,421104,424091,423102,417075,0,419103,0]},
302004:{m:1,c:[418087,424088,411091,420088,413092,0,419100,0]},
299004:{m:1,c:[423085,425072,412088,411092,410080,0,425073,0]},
410123:{m:1,c:[415157,424136,418128,412126,0,0,0,0]},
263037:{m:1},
261024:{m:1},
253018:{m:1},
157048:{m:1},
226044:{m:1},
226043:{m:1,c:[576087,436090,526099,0,526098,536091,0,0]},
556092:{m:7},
254038:{m:1,c:[0,0,436064,466066,466090,556092,546060,496072]},
466090:{m:7},
556093:{m:7},
257038:{m:1,c:[526096,526102,456062,576063,496084,556093,536077,496071]},
526102:{m:7},
526096:{m:7},
506084:{m:7},
253035:{m:1,c:[526103,0,566067,486072,506084,0,506070,446064]},
526103:{m:7},
496060:{m:1,c:[0,0,0,0,486060,0,496088,0]},
496088:{m:1},
536060:{m:1},
556094:{m:7},
546083:{m:7},
436099:{m:7},
466091:{m:7},
486060:{m:1,c:[556095,0,0,0,556094,546083,436099,466091]},
556095:{m:7},
466092:{m:7},
556096:{m:7},
566054:{m:1,c:[556096,0,466092,0,516072,486065,486066,566059]},
420032:{m:1,c:[0,0,466093,436100,496089,546084,425015,409048]},
418037:{m:1,c:[0,0,566086,506088,476101,526106,420033,409047]},
409044:{m:1,c:[0,0,536099,456082,496090,546085,410031,409046]},
413047:{m:1,c:[0,0,516109,476102,556099,526107,409045,416038]},
413052:{m:1,c:[0,0,436104,546086,0,0,415050,436103]},
424042:{m:1,c:[0,0,556100,466097,0,0,526108,413053]},
343013:{m:1,c:[0,0,409044,424038,476104,424042,420030,336015]},
476105:{m:7},
466098:{m:7},
339013:{m:1,c:[0,0,411040,413047,413052,556101,340013,419025]},
413030:{m:1,c:[466036,0,425007,436105,496036,546031,424022,420023]},
436105:{m:1},
546087:{m:1},
456083:{m:1},
556101:{m:1,c:[0,0,536100,456083,0,0,496091,546087]},
506090:{m:7},
446086:{m:7},
576095:{m:7},
436103:{m:1,c:[0,0,506090,456084,446086,576095,476105,466098]},
456084:{m:7},
536101:{m:7},
496092:{m:7},
546088:{m:7},
446087:{m:7},
496091:{m:1,c:[0,0,446087,576096,496092,0,536101,546088]},
576096:{m:7},
456085:{m:7},
436104:{m:1,c:[0,0,0,0,0,0,456085,536102]},
536102:{m:7},
496093:{m:7},
546086:{m:1,c:[0,0,0,0,0,0,496093,546089]},
546089:{m:7},
436106:{m:7},
536100:{m:1,c:[0,0,0,0,0,0,436106,0]},
576097:{m:7},
456086:{m:7},
466097:{m:1,c:[0,0,0,0,0,0,456086,576097]},
556102:{m:7},
526109:{m:7},
476106:{m:7},
516110:{m:7},
436107:{m:1},
418028:{m:1,c:[0,486039,576098,409027,526042,506036,413032,409026]},
576098:{m:1},
344008:{m:1,c:[0,456087,0,409128,0,423040,0,341012]},
536103:{m:1},
423040:{m:1,c:[0,0,0,496094,0,0,0,415049]},
496094:{m:1},
456087:{m:1,c:[0,0,0,546090,0,0,0,536103]},
546090:{m:1},
566087:{m:7},
436108:{m:7},
576099:{m:7},
456088:{m:7},
496095:{m:7},
526108:{m:1,c:[0,0,496095,456088,516110,526109,476106,556102]},
546091:{m:7},
516111:{m:7},
486094:{m:7},
556100:{m:1,c:[0,0,0,0,0,0,486094,516111]},
456089:{m:1},
476104:{m:1,c:[0,0,456089,566088,0,0,436107,486093]},
506091:{m:7},
566088:{m:1,c:[0,0,0,0,0,0,0,506091]},
446088:{m:7},
486093:{m:1,c:[0,0,446088,546091,0,436108,576099,566087]},
456090:{m:7},
466093:{m:1,c:[0,0,0,0,0,0,0,456090]},
536104:{m:7},
496096:{m:7},
576100:{m:7},
456091:{m:7},
536105:{m:7},
496097:{m:7},
546092:{m:7},
436109:{m:7},
466099:{m:7},
556103:{m:7},
526110:{m:7},
476107:{m:7},
506088:{m:1,c:[0,0,0,0,0,0,516112,0]},
516112:{m:7},
486095:{m:7},
516113:{m:7},
526106:{m:1,c:[0,0,0,0,0,0,516113,486095]},
456092:{m:7},
506092:{m:7},
446089:{m:7},
576101:{m:7},
456093:{m:7},
536106:{m:7},
496098:{m:7},
546093:{m:7},
436110:{m:7},
466100:{m:7},
556104:{m:7},
526111:{m:7},
476108:{m:7},
496089:{m:1,c:[0,0,0,0,0,0,516114,476108]},
516114:{m:7},
436111:{m:7},
466101:{m:7},
536099:{m:1,c:[0,0,0,0,0,0,436111,466101]},
556105:{m:7},
526112:{m:7},
476109:{m:7},
516115:{m:7},
486096:{m:7},
566089:{m:7},
506093:{m:7},
446090:{m:7},
486097:{m:7},
566090:{m:7},
506094:{m:7},
446091:{m:7},
576102:{m:7},
456094:{m:7},
476102:{m:1,c:[0,0,0,0,0,0,576102,456094]},
526107:{m:1,c:[0,0,0,0,0,0,536107,0]},
536107:{m:7},
456095:{m:7},
536108:{m:7},
496099:{m:7},
546094:{m:7},
436112:{m:7},
466102:{m:7},
556106:{m:7},
526113:{m:7},
436113:{m:7},
466103:{m:7},
556107:{m:7},
526114:{m:7},
476110:{m:7},
496090:{m:1,c:[0,0,0,0,0,0,0,476110]},
496100:{m:7},
546095:{m:7},
456096:{m:7},
536109:{m:7},
496101:{m:7},
546096:{m:7},
436114:{m:7},
466104:{m:7},
556108:{m:7},
526115:{m:7},
476111:{m:7},
526116:{m:7},
476112:{m:7},
516116:{m:7},
486098:{m:7},
566091:{m:7},
506095:{m:7},
446092:{m:7},
576103:{m:7},
456097:{m:7},
536110:{m:7},
496102:{m:7},
576104:{m:7},
456098:{m:7},
115002:{m:1,c:[0,0,419026,0,0,0,496103,0]},
143001:{m:1,c:[0,0,0,0,0,0,176001,546097]},
496103:{m:1,c:[0,0,0,0,0,0,536111,456099]},
536112:{m:1},
546097:{m:1,c:[0,0,0,0,0,0,536112,456100]},
456099:{m:1,c:[0,0,0,0,0,0,526117,0]},
526117:{m:1},
556110:{m:7},
466105:{m:1,c:[0,0,0,0,0,0,546098,556110]},
546098:{m:7},
436116:{m:7},
446093:{m:1,c:[0,0,0,0,0,0,466106,436116]},
466106:{m:7},
436115:{m:1,c:[0,0,0,0,0,0,0,556111]},
556111:{m:7},
526118:{m:7},
556109:{m:1,c:[0,0,0,0,0,0,526118,0]},
476113:{m:7},
516117:{m:7},
486099:{m:7},
466107:{m:7},
476101:{m:1,c:[0,0,556112,466107,506095,446092,506092,456092]},
556112:{m:7},
526119:{m:7},
476114:{m:7},
526105:{m:1,c:[476114,0,476113,526119,486098,566091,576101,446089]},
516118:{m:7},
486100:{m:7},
556097:{m:1,c:[486100,516118,486099,516117,476112,516116,536106,456093]},
566092:{m:7},
536113:{m:7},
496104:{m:7},
546099:{m:7},
436117:{m:7},
466108:{m:7},
546084:{m:1,c:[0,0,466108,436117,436114,466104,526111,556104]},
436101:{m:1,c:[0,456101,546099,496104,556108,526115,466100,436110]},
456101:{m:7},
536114:{m:7},
466094:{m:1,c:[536114,496105,536113,566092,476111,526116,546093,496098]},
496105:{m:7},
476115:{m:7},
516119:{m:7},
576093:{m:1,c:[0,0,0,0,516119,476115,536105,496097]},
486101:{m:7},
526104:{m:1,c:[0,0,0,0,566093,486101,576100,456091]},
566093:{m:7},
436100:{m:1,c:[0,0,0,0,0,506096,536104,496096]},
506096:{m:7},
446094:{m:7},
446084:{m:1,c:[0,0,0,0,576105,446094,546092,436109]},
576105:{m:7},
456102:{m:7},
506089:{m:1,c:[0,0,0,0,456102,506097,466099,556103]},
506097:{m:7},
566086:{m:1,c:[0,0,0,0,566094,0,526110,476107]},
566094:{m:7},
419037:{m:1,c:[476116,0,446084,506089,556097,526105,413048,415043]},
412042:{m:1,c:[0,516120,526104,576093,436101,466094,416039,425014]},
456103:{m:1},
536111:{m:1,c:[0,0,456103,0,0,0,466105,556109]},
456100:{m:1,c:[0,0,0,536115,0,0,436115,446093]},
536115:{m:1},
496106:{m:7},
516120:{m:1,c:[0,0,0,0,0,0,0,496106]},
476116:{m:1,c:[0,0,0,0,0,0,546100,0]},
546100:{m:7},
446095:{m:7},
576106:{m:7},
456104:{m:7},
536116:{m:7},
496107:{m:7},
546101:{m:7},
436118:{m:7},
456082:{m:1,c:[0,0,546096,496101,436118,546101,556105,526112]},
466109:{m:7},
496108:{m:7},
516109:{m:1,c:[0,0,456097,576103,466109,496108,506094,446091]},
546102:{m:7},
436119:{m:7},
466110:{m:7},
436120:{m:7},
466111:{m:7},
446085:{m:1,c:[556113,466111,546095,496100,456104,576106,486096,566089]},
556113:{m:7},
526120:{m:7},
576094:{m:1,c:[0,526120,536109,456096,496107,536116,476109,516115]},
476103:{m:1,c:[476117,0,496102,536110,436119,546102,486097,566090]},
476117:{m:7},
516121:{m:7},
536098:{m:1,c:[436120,516121,456098,576104,446095,466110,506093,446090]},
556114:{m:7},
526121:{m:7},
476118:{m:7},
526122:{m:7},
436121:{m:7},
556099:{m:1,c:[0,0,436121,0,0,0,536108,456095]},
466112:{m:7},
556115:{m:7},
526123:{m:7},
476119:{m:7},
526124:{m:7},
546085:{m:1,c:[0,0,0,526124,0,0,526114,556107]},
424038:{m:1,c:[0,476120,576094,446085,436102,466095,421039,418038]},
411040:{m:1,c:[466113,0,536098,476103,556098,466096,417028,416037]},
456105:{m:7},
476120:{m:1,c:[0,0,0,0,0,0,0,456105]},
466113:{m:1,c:[0,0,0,0,0,0,536117,0]},
536117:{m:7},
446096:{m:7},
576107:{m:7},
456106:{m:7},
466095:{m:1,c:[0,0,556115,466112,456106,576107,526113,556106]},
536118:{m:7},
436102:{m:1,c:[0,0,476119,526123,496109,536118,466103,436113]},
496109:{m:7},
486102:{m:7},
556098:{m:1,c:[0,0,556114,526121,446096,486102,466102,436112]},
566095:{m:7},
466096:{m:1,c:[0,0,476118,526122,566095,506098,546094,496099]},
506098:{m:7},
421025:{m:1,c:[486037,466035,425004,425005,556035,0,419022,526125]},
341014:{m:1,c:[425019,0,338006,413035,476121,0,423026,415032]},
425019:{m:1,c:[0,0,419039,516123,0,0,566096,506099]},
486104:{m:1},
566097:{m:1},
425018:{m:1,c:[0,0,506100,566097,0,0,420038,486104]},
506100:{m:1},
339011:{m:1,c:[446097,0,412029,409030,425018,0,340010,423028]},
506101:{m:1},
446097:{m:1,c:[0,0,0,0,0,0,506101,446098]},
446098:{m:1},
516124:{m:7},
486105:{m:7},
566098:{m:7},
516123:{m:1,c:[0,0,516124,486105,0,0,556116,566098]},
556116:{m:7},
526126:{m:7},
476122:{m:7},
516125:{m:7},
556117:{m:7},
466114:{m:7},
556118:{m:7},
526127:{m:7},
476123:{m:7},
516126:{m:7},
486106:{m:7},
566099:{m:7},
476124:{m:7},
576108:{m:7},
476121:{m:1,c:[0,0,516122,466115,0,0,486103,0]},
466115:{m:1,c:[0,0,516127,0,0,0,0,0]},
516127:{m:7},
486107:{m:7},
506099:{m:1,c:[0,0,516125,0,0,0,486107,0]},
486108:{m:7},
566096:{m:1,c:[486108,0,526126,476122,566100,0,556117,466114]},
566100:{m:7},
506102:{m:7},
516122:{m:1,c:[506102,0,526127,556118,0,0,476123,476124]},
446099:{m:7},
486109:{m:7},
337013:{m:1,c:[409015,446100,340012,423027,0,0,422010,409031]},
409015:{m:1,c:[0,0,418042,566101,0,0,506103,566102]},
546103:{m:1},
526128:{m:7},
476125:{m:7},
506104:{m:7},
446101:{m:7},
446100:{m:1,c:[0,0,516128,576110,0,0,576109,546103]},
496110:{m:1},
536119:{m:1,c:[0,0,496110,0,0,0,0,0]},
576112:{m:1},
417015:{m:1},
411014:{m:1},
413013:{m:1},
411017:{m:1},
418014:{m:1,c:[415103,423079,418080,420079,411081,416080,415102,419091]},
424080:{m:1},
424079:{m:1},
419092:{m:1},
420080:{m:1},
466116:{m:7},
556119:{m:7},
566101:{m:1,c:[0,0,526128,476125,0,0,466116,556119]},
526129:{m:7},
476126:{m:7},
516128:{m:1,c:[0,0,506104,446101,0,0,526129,476126]},
466117:{m:7},
526125:{m:1,c:[446099,0,516126,486106,0,0,486109,556120]},
556120:{m:7},
486103:{m:1,c:[0,0,566099,576108,0,0,526130,0]},
526130:{m:7},
496111:{m:7},
536120:{m:7},
576110:{m:1,c:[0,0,466117,496111,0,0,536120,0]},
446103:{m:7},
576113:{m:7},
456107:{m:7},
506103:{m:1,c:[0,0,446103,536121,0,0,576113,456107]},
536121:{m:7},
496112:{m:7},
536122:{m:7},
566102:{m:1,c:[0,0,496112,536122,0,0,0,0]},
496113:{m:7},
576109:{m:1,c:[0,0,496113,0,0,0,0,0]},
576114:{m:7},
456108:{m:7},
526131:{m:7},
476127:{m:7},
422010:{m:1,c:[415016,420010,419013,421011,506105,486110,419014,411015]},
486110:{m:1},
409031:{m:1,c:[576111,446102,421030,416031,526132,576112,413069,409066]},
526132:{m:1},
147002:{m:1,c:[0,0,476128,0,0,0,0,0]},
476128:{m:1,c:[0,0,476129,0,0,0,0,0]},
137004:{m:1,c:[0,0,0,516129,0,0,0,0]},
516129:{m:1,c:[0,0,0,486111,0,0,0,0]},
486111:{m:1,c:[0,0,506106,566103,0,0,0,0]},
506106:{m:1},
476129:{m:1,c:[0,0,516130,476130,0,0,0,0]},
516131:{m:7},
486112:{m:7},
566103:{m:1,c:[0,0,486112,516131,0,0,0,0]},
566104:{m:7},
506107:{m:7},
516130:{m:1,c:[0,0,566104,506107,0,0,0,0]},
516132:{m:7},
476131:{m:7},
516133:{m:7},
486113:{m:7},
566105:{m:7},
536123:{m:7},
496114:{m:7},
409066:{m:1,c:[0,0,496114,546104,0,0,0,0]},
546104:{m:7},
456109:{m:7},
506108:{m:7},
411015:{m:1,c:[516133,446104,516132,486113,506108,0,476131,456109]},
446104:{m:7},
506109:{m:7},
446105:{m:7},
576115:{m:7},
413069:{m:1,c:[506109,446105,566105,536123,0,0,456110,576115]},
456110:{m:7},
506110:{m:7},
446106:{m:7},
576116:{m:7},
446107:{m:7},
576117:{m:7},
446102:{m:1,c:[0,0,576117,456111,0,0,0,0]},
456111:{m:7},
536124:{m:7},
496115:{m:7},
546105:{m:7},
546106:{m:7},
436122:{m:7},
506105:{m:1,c:[0,0,546106,436122,0,0,0,0]},
415016:{m:1,c:[526131,536124,576114,476127,0,0,456108,466118]},
466118:{m:7},
556121:{m:7},
420010:{m:1,c:[496115,546105,506110,446106,0,0,556121,546107]},
546107:{m:7},
436123:{m:7},
466119:{m:7},
576111:{m:1,c:[0,0,576116,446107,0,0,436123,466119]},
486114:{m:1},
424025:{m:1,c:[423030,566106,413037,420024,446108,486114,415033,556122]},
546108:{m:1},
412030:{m:1,c:[536119,0,424025,526133,0,0,421062,0]},
420008:{m:1,c:[417047,411060,411059,420056,496117,576118,409065,410049]},
576118:{m:1},
371001:{m:1,c:[424070,456112,410060,415087,546110,0,0,0]},
546110:{m:1},
419058:{m:1,c:[546108,0,423061,536125,0,0,436125,0]},
436125:{m:1},
576119:{m:7},
456113:{m:7},
536126:{m:7},
496118:{m:7},
546111:{m:7},
436126:{m:7},
413068:{m:1,c:[0,0,466120,0,0,0,0,0]},
466120:{m:7},
496119:{m:7},
546112:{m:7},
436127:{m:7},
486115:{m:7},
566107:{m:7},
413067:{m:1,c:[496119,486116,546112,436127,0,0,486115,566107]},
486116:{m:7},
576120:{m:7},
456114:{m:7},
536127:{m:7},
496120:{m:7},
546113:{m:7},
496121:{m:7},
576121:{m:7},
456115:{m:7},
536128:{m:7},
423013:{m:1,c:[0,0,536128,496122,0,0,0,0]},
496122:{m:7},
436128:{m:7},
466121:{m:7},
446109:{m:7},
576122:{m:7},
423061:{m:1,c:[446109,456116,436128,576122,0,0,466121,0]},
456116:{m:7},
160016:{m:1,c:[424069,436124,419076,410059,576123,546109,409076,496116]},
456117:{m:7},
536129:{m:7},
496123:{m:7},
566108:{m:7},
556123:{m:7},
466122:{m:7},
576123:{m:1,c:[556123,466122,456117,566108,0,0,536129,496123]},
496124:{m:7},
546114:{m:7},
436129:{m:7},
466123:{m:7},
421063:{m:1,c:[556124,0,496124,466123,0,0,546114,436129]},
556124:{m:7},
526134:{m:7},
476132:{m:7},
516134:{m:1},
446108:{m:1,c:[516134,0,476132,566109,0,0,526134,0]},
566109:{m:7},
516135:{m:7},
486117:{m:7},
566110:{m:7},
476133:{m:7},
516136:{m:7},
486118:{m:7},
423030:{m:1,c:[516136,486118,516135,476133,566111,0,486117,566110]},
566111:{m:7},
466124:{m:7},
423026:{m:1,c:[409086,425060,415101,425059,411079,556125,421080,418078]},
556126:{m:7},
526135:{m:7},
556127:{m:7},
526136:{m:7},
476134:{m:7},
516137:{m:7},
556125:{m:1,c:[476134,0,556126,526135,516137,0,526136,556127]},
486119:{m:7},
526137:{m:7},
566106:{m:1,c:[0,0,466124,526137,0,0,486119,0]},
556128:{m:7},
526138:{m:7},
476135:{m:7},
516138:{m:7},
486120:{m:7},
566112:{m:7},
476136:{m:7},
556122:{m:1,c:[476135,566112,556128,516138,476136,0,526138,486120]},
556129:{m:7},
526139:{m:7},
476137:{m:7},
546109:{m:1,c:[0,0,476137,0,0,0,0,0]},
546115:{m:7},
496125:{m:7},
546116:{m:7},
436130:{m:7},
536130:{m:7},
526140:{m:7},
446110:{m:7},
476138:{m:7},
476139:{m:7},
421062:{m:1,c:[0,0,421063,526141,0,0,0,0]},
526141:{m:1,c:[0,0,506111,0,0,0,0,0]},
506111:{m:7},
456118:{m:7},
436124:{m:1,c:[476139,446111,556129,476138,456118,0,526139,446110]},
446111:{m:7},
456119:{m:7},
496116:{m:1,c:[496125,526140,546115,436130,456119,0,546116,536130]},
536125:{m:1,c:[0,0,536131,0,0,0,0,0]},
536131:{m:7},
576124:{m:7},
556130:{m:7},
456120:{m:7},
476140:{m:7},
516139:{m:7},
456121:{m:7},
456112:{m:1,c:[556130,536132,576124,456121,456120,0,476140,516139]},
536132:{m:7},
446112:{m:7},
476130:{m:1,c:[0,0,446112,0,0,0,0,0]},
576125:{m:7},
456122:{m:7},
411060:{m:1,c:[576125,506112,576120,536127,456122,0,456114,496120]},
506112:{m:7},
446113:{m:7},
415019:{m:1,c:[446113,576126,496121,576121,0,0,546113,456115]},
576126:{m:7},
415015:{m:1,c:[415019,423013,419015,411018,436131,0,412013,413068]},
436131:{m:1},
466125:{m:7},
466126:{m:7},
496117:{m:1,c:[0,0,466126,566113,0,0,0,0]},
566113:{m:7},
409065:{m:1,c:[466125,506113,576119,456113,0,0,0,0]},
506113:{m:7},
446114:{m:7},
410049:{m:1,c:[446114,576127,536126,496118,0,0,0,0]},
576127:{m:7},
412013:{m:1,c:[456123,0,546111,436126,0,0,0,0]},
456123:{m:7},
486121:{m:1},
153007:{m:1,c:[425051,506114,415084,416069,516140,486121,411067,0]},
506114:{m:1},
526133:{m:1,c:[0,0,526142,0,0,0,526143,0]},
155012:{m:1,c:[456124,0,386002,0,0,0,476141,0]},
148010:{m:1,c:[415086,0,415085,411068,456125,0,413075,0]},
372001:{m:1,c:[446115,0,373001,0,0,0,379001,0]},
466127:{m:7},
556131:{m:7},
526144:{m:7},
476142:{m:7},
373001:{m:1,c:[476142,516141,556131,466127,0,0,526144,0]},
516141:{m:7},
446115:{m:1,c:[0,0,496126,0,0,0,0,0]},
496126:{m:7},
546117:{m:7},
436132:{m:7},
436133:{m:7},
496127:{m:7},
536133:{m:7},
496128:{m:7},
456125:{m:1,c:[536133,496128,546117,496127,546118,0,436132,436133]},
546118:{m:7},
516142:{m:7},
476141:{m:1,c:[0,0,516142,556132,0,0,0,0]},
556132:{m:7},
506115:{m:7},
446116:{m:7},
576128:{m:7},
456126:{m:7},
536134:{m:7},
456127:{m:7},
456124:{m:1,c:[0,0,456127,536135,0,0,506115,0]},
536135:{m:7},
446117:{m:7},
576129:{m:7},
456128:{m:7},
516140:{m:1,c:[446117,576129,446116,576128,456128,0,536134,456126]},
516143:{m:7},
566114:{m:7},
496129:{m:7},
546119:{m:7},
436134:{m:7},
526143:{m:1,c:[0,0,436134,0,0,0,0,0]},
526142:{m:1,c:[566115,0,516143,566114,0,0,546119,496129]},
566115:{m:7},
165005:{m:1,c:[162006,161008,415057,516099,209001,207004,496130,0]},
496130:{m:1},
556060:{m:1,c:[0,0,0,0,476143,0,0,0]},
476143:{m:1},
423093:{m:1,c:[415125,409121,417082,421106,423098,0,419110,0]},
217044:{m:1,c:[424001,409011,418010,413011,422007,425118,418012,0]},
220042:{m:1,c:[419011,418011,411011,409010,423010,0,422008,0]},
215039:{m:1,c:[409012,421009,410013,424004,412011,0,420006,416145]},
222041:{m:1},
257001:{m:1},
415013:{m:1,c:[424146,415160,424145,409152,413138,0,419150,0]},
424005:{m:1,c:[413137,418134,418133,412131,410132,0,416143,0]},
424109:{m:1,c:[417128,409151,424144,417130,417129,0,409149,0]},
418109:{m:1,c:[416142,421131,410131,423128,409150,0,411145,0]},
304007:{m:1},
305005:{m:1},
256001:{m:1,c:[412010,0,417010,0,0,0,0,0]},
215040:{m:1,c:[417011,416008,424003,422009,417012,0,417013,0]},
410138:{m:1,c:[424151,409154,424150,417133,420140,0,419152,0]},
416149:{m:1,c:[425120,411147,423131,421134,410139,0,412134,0]},
412134:{m:1,c:[413141,409156,416152,416153,0,0,0,0]},
420140:{m:1,c:[410140,0,425123,0,0,0,0,0]},
419152:{m:1,c:[416151,0,416150,0,0,0,0,0]},
410139:{m:1,c:[417134,0,419153,0,0,0,0,0]},
421134:{m:1,c:[411148,425121,421135,411149,415162,411151,411150,418136]},
411147:{m:1,c:[409155,0,415163,0,0,0,0,0]},
409154:{m:1,c:[420142,0,424152,0,0,0,0,0]},
417133:{m:1,c:[418137,0,412135,0,0,0,0,0]},
411150:{m:1,c:[411153,412147,421138,0,416155,0,421140,0]},
415162:{m:1,c:[425122,0,420141,425129,423135,0,412139,0]},
425121:{m:1,c:[421137,0,423132,0,0,0,0,0]},
411149:{m:1,c:[411152,0,421136,0,0,0,0,0]},
410147:{m:1,c:[424153,418145,416165,420148,416166,0,417139,409164]},
415173:{m:6},
421149:{m:7},
226062:{m:1,c:[416007,0,0,0,0,0,0,0]},
301005:{m:1},
307006:{m:1,c:[409097,0,0,0,0,0,0,0]},
421008:{m:1,c:[476033,0,413096,0,0,0,0,0]},
424002:{m:1},
226061:{m:1},
226064:{m:1},
302005:{m:1,c:[0,0,423091,0,0,0,0,0]},
412010:{m:1},
417010:{m:1},
398002:{m:1},
416007:{m:1,c:[418088,0,0,0,0,0,0,0]},
413096:{m:1,c:[0,0,418089,0,0,0,0,0]},
418088:{m:1,c:[412090,0,0,0,0,0,0,0]},
418089:{m:1,c:[0,0,410083,0,0,0,0,0]},
424004:{m:1,c:[410091,420095,423092,423093,420104,0,415128,417083]},
409011:{m:1,c:[424097,421096,420094,420106,419113,410089,420105,0]},
413011:{m:1,c:[409104,413112,417081,425089,419123,0,423099,0]},
418011:{m:1,c:[410090,411113,411101,410095,421102,0,410096,0]},
409010:{m:1,c:[416099,416110,415124,418106,425090,0,411114,424108]},
436135:{m:7},
546120:{m:7},
436136:{m:7},
466128:{m:7},
556133:{m:7},
526145:{m:7},
516144:{m:3},
486122:{m:3},
566116:{m:3},
506116:{m:3},
446118:{m:3},
576130:{m:3},
446119:{m:3},
416008:{m:1,c:[436135,576130,546120,446118,446119,0,576131,0]},
576131:{m:3},
456129:{m:3},
422009:{m:1,c:[436136,506116,466128,566116,456129,0,536136,0]},
536136:{m:3},
496131:{m:3},
421009:{m:1,c:[556133,486122,526145,516144,496131,0,546121,0]},
546121:{m:3},
420105:{m:1,c:[412121,456004,526007,436007,456005,0,436008,0]},
419117:{m:1,c:[423096,419119,415130,415135,423107,412104,417094,416115]},
416106:{m:1,c:[418104,420102,421099,409114,415134,412106,420103,421108]},
410120:{m:1},
410154:{m:1,c:[425134,413159,421157,411167,415176,416175,413160,417149]},
424101:{m:1,c:[423139,423140,418148,412151,420152,409169,423141,410151]},
425085:{m:1,c:[411106,420151,418101,0,0,0,0,0]},
425132:{m:1,c:[411166,421153,417145,410152,410153,436006,417146,446004]},
419115:{m:1,c:[415175,419164,420153,425133,418151,409173,421156,410154]},
417152:{m:1,c:[416178,423145,423144,420154,415180,0,415177,0]},
412152:{m:1,c:[421169,413168,419174,416183,423159,413169,425144,411176]},
413156:{m:1,c:[410162,417157,409176,409177,423151,415183,424166,416180]},
476144:{m:7},
516145:{m:7},
486123:{m:7},
566117:{m:7},
456130:{m:7},
421161:{m:1,c:[476144,566117,516145,486123,456130,0,536137,0]},
536137:{m:7},
420151:{m:1,c:[413156,436002,421161,466004,423146,0,496132,0]},
556134:{m:7},
496132:{m:1,c:[556134,0,526146,0,0,0,0,0]},
526146:{m:7},
419132:{m:6},
160020:{m:1,c:[418019,421016,416043,411045,425035,419081,419082,416075]},
154020:{m:1,c:[409051,410035,424043,425020,423077,409064,409078,411075]},
158017:{m:1,c:[425023,417031,425021,410036,424073,424086,411076,425036]},
154021:{m:1,c:[424072,415090,415052,412049,486089,0,546077,421047]},
163001:{m:1,c:[413055,412048,425024,419045,476095,576089,446081,436094]},
159020:{m:1,c:[418045,412050,0,419046,546078,516105,0,0]},
152018:{m:1,c:[419042,419041,412047,417032,576088,466085,516104,436093]},
158018:{m:1,c:[411046,410037,418044,409052,410117,418121,556088,506085]},
150018:{m:1,c:[412046,425022,419043,418043,409094,410077,417072,466083]},
149016:{m:1,c:[423041,410038,424044,420039,416089,456075,410076,418083]},
148020:{m:1,c:[423074,419078,417033,419044,416120,420120,421114,418116]},
149017:{m:1,c:[419079,410062,413054,415051,0,0,0,0]},
413091:{m:7},
424084:{m:7},
409096:{m:7},
377009:{m:1,c:[413080,420074,415095,413081,415096,415097,0,0]},
169001:{m:1,c:[413082,417063,421079,416078,420075,0,0,0]},
381008:{m:1,c:[416091,425069,417073,415112,421087,418086,0,0]},
212039:{m:1,c:[416092,423084,417074,425070,0,410079,0,0]},
221038:{m:1},
384002:{m:1},
375009:{m:1},
379007:{m:1},
146002:{m:1,c:[426001,421059,0,421060,0,423057,0,0]},
163002:{m:1,c:[415070,427001,0,0,0,0,0,0]},
406001:{m:1},
272001:{m:1},
255021:{m:1},
266022:{m:1},
257016:{m:1},
254024:{m:1},
224018:{m:1},
};
/*
ThomasLuther
 VoWe
WipperFeld
Prohi
*/

 goog.require('goog.async.Delay');
 goog.require('goog.net.XhrIo');
 goog.require('goog.structs.Map');
 goog.require('goog.Uri.QueryData');

 //prevent older browsers like FireFox 3.6.13 from complaining
 function log(msg) {
  try {
   console.log(msg);
  } catch(e) {
  }
 }

 function modulo(v,pow) {
  return (v>>pow)<<pow;
 } 
log(root);
 var currParent=root;
 var currMaterial=2;
 var parentColumn='c111';
 var currNode=ocTree[root].parentColumn;
 var cursorLevel=23; // cube with size of 2^cursorLevel meter
 var zoomLevel=0;
 //const
 var baseDiff=Math.pow(2,cursorLevel);
 var levelLen=baseDiff;
 var rotX=0;
 var rotY=0;
 var rotZ=0;
 var cursorPos=[0,0,0]; // in meter
 //const
 var childNames=['c000','c001','c010','c011','c100','c101','c110','c111'];
 //const
 var pane=document.getElementById('pane');
 //const
 var ctx=pane.getContext('2d');
 //const
 var xBox=document.getElementById('xBox').getContext('2d');
 //const
 var yBox=document.getElementById('yBox').getContext('2d');
 //const
 var zBox=document.getElementById('zBox').getContext('2d');
 // fit 2^24=16777216 m on 160px:
 var meterPerPixel=55000;
 //const
 var SingularMeridian=13.7414;
 //const
 var materials={
  1:{r:20, g:20 ,b:20, name:'air'},
  2:{r:40, g:40 ,b:200,name:'water'},
  3:{r:40, g:220,b:20 ,name:'green'},
  4:{r:240,g:220,b:20 ,name:'desert'},
  5:{r:240,g:220,b:220,name:'ice'},
  6:{r:240,g:40 ,b:20 ,name:'urban'},
  7:{r:156,g:90 ,b:60 ,name:'crust'},
  8:{r:245,g:200,b:150,name:'LimeStone'},
  9:{r:245,g:220,b:150,name:'SandStone'},
  10:{r:40,g:40, b:40, name:'iron'},
  11:{r:240,g:220,b:20,name:'gold'},
 /* ToDo: https://en.wikipedia.org/wiki/Structure_of_the_Earth :
  1. continental crust – 2. oceanic crust – 3. upper mantle – 4. lower mantle – 5. outer core – 6. inner core –
 */
 };
 var recentMaterials=[1,2,3,4,5,6,7,8,9,10,11];
 var recentMaterialsPos=0;

 function setMaterial() {
  var col='rgb('+
   materials[currMaterial].r+','+
   materials[currMaterial].g+','+
   materials[currMaterial].b+')';
  document.getElementById('selectedMaterial').style.backgroundColor=col;
  document.getElementById('selectedMaterialName').innerHTML=materials[currMaterial].name;
 }

 function selectedMaterial(mat) {
  currMaterial=mat.id.substring(3);
  recentMaterials=[currMaterial].concat(recentMaterials);
  recentMaterialsPos=0;
  document.getElementById('selectMaterial').style.display='none';
  document.getElementById('palette').style.display='block';
  setMaterial();
 }

 function selectMaterial() {
  var t=document.getElementById('selectMaterial').style;
  t.display='block';
  t=document.getElementById('palette').style.display='none';
 }

 function toggleMaterial(m) {
  var mat=m.id.substring(7);
  var allM=document.getElementById('showMatAll');
  if ('All'==mat) {
   for(var m in materials) {
    if('air'!=materials[m].name) {
     document.getElementById('showMat'+m).checked=allM.checked;
    }
   }
  } else {
   var allChecked=false;
   for(var m in materials) {
    if('air'!=materials[m].name) {
     allChecked=allChecked&&document.getElementById('showMat'+m).checked;
    }
   }
   allM.checked=allChecked;
  }
  draw();
 }

 var animStage;
 var animTarget;

 function animate() {
  var delay=500;
  if(0==animStage) {
   if(zoomLevel>0) { // zoom out
    zoomLevel--;
   } else {
    animStage++;
   }
  }
  if(1==animStage) { //rotate
   delay=800;
   if (rotZ>0) {
    rotZ=(rotZ-1)%4;
   } else {
    animStage++;
   }
  }
  if(2==animStage) {
   //if(zoomLevel<15) { // zoom in
   delay=100;
   if(meterPerPixel>10000) { // zoom in
    //zoomLevel++;
    meterPerPixel-=5000;
   } else {
    cursorPos[0]=4016256;
    cursorPos[1]=0;
    cursorPos[2]=4938304;
    cursorLevel=8;
    zoomLevel=8;
    currNode=225048;
    draw();
    return;
   }
  }
  draw();
  var delay = new goog.async.Delay(animate, delay);
  delay.start();
 }

 var landmarks={
  'CristoRedentor' :{lat:-22.95194, lon:-43.21056, alt:700},
  'GoldRider'      :{lat: 29.97917, lon: 31.13435, alt:110},
  'GreatPyramid'   :{lat: 29.97917, lon: 31.13435, alt: 30},
  'IlColosseo'     :{lat: 41.89017, lon: 12.49227, alt:161}, // https://www.facebook.com/pages/Colosseum/106151256083561
  'LockSchuppen'   :{lat: 51.06713, lon: 13.74147, alt:120},
  'StatueOfLiberty':{lat: 40.68917, lon:-74.04444, alt: 20},
  'TourEiffel'     :{lat: 40.68917, lon:-74.04444, alt: 30},
 }//ToDo: AyersRock FluegelAuto GranPiramide KreuzKirche SecretCity

 function warn(s) {
  alert(s);
 }

 function hot(hot) {
  animStage=0;
  animTarget=hot;
  animate();
  return false;
 }

 //http://www.daveoncode.com/2009/11/17/goog-net-xhrio-make-simple-ajax-calls-with-google-closure/
 function remoteAdd() {
  document.getElementById('node').innerHTML='*creating...*';
  var request = new goog.net.XhrIo();
  var data = goog.Uri.QueryData.createFromMap(new goog.structs.Map({
   op: 'addChild',
   node: currParent,
   child: parentColumn,
   material: currMaterial}));

  goog.events.listen(request, 'complete', function() {
   if (request.isSuccess()) {
    var json=request.getResponseJson();
    log(json);
    if ('error'==json.status) {
     log("Server failed: "+ request.getStatusText());
    } else {
     currNode=json.newId;
     ocTree[currParent][parentColumn] = currNode;
     document.getElementById('node').innerHTML=currNode;
     ocTree[currNode] = {
      material: currMaterial,
      parent: currParent};
     draw();
    }
   } else {
    log("Server failed: "+ request.getStatusText());
   }
  });
  request.send('/earthOp?', 'POST', data.toString());
  return false;
 }

 function remoteSet() {
  document.getElementById('material').innerHTML='...';
  var request = new goog.net.XhrIo();
  var data = goog.Uri.QueryData.createFromMap(new goog.structs.Map({
   op: 'set',
   node: currNode,
   material: ocTree[currNode].material}));

  goog.events.listen(request, 'complete', function() {
   if (request.isSuccess()) {
    var json=request.getResponseJson();
    //log(json);
    if ('error'==json.status) {
     warn("Server failed: "+ request.getStatusText());
     //ToDo
    } else {
     draw();
    }
   } else {
    warn("Server failed: "+ request.getStatusText());
    //alert("Server failed: "+ request.getResponseText());
   }
  });
  request.send('/earthOp?', 'POST', data.toString());
  return false;
 }

 function rotColName(xi,yi,zi) {
  var cName='c'+xi+''+yi+''+zi;
  if (rotZ==1) {
   cName='c'+yi+''+(1-xi)+''+zi;      
  }
  if (rotZ==2) {
   cName='c'+(1-xi)+''+(1-yi)+''+zi;      
  }
  if (rotZ==3) {
   cName='c'+(1-yi)+''+(xi)+''+zi;      
  }
  return cName;
 }

 function drawTreeNode(node,x,y,z,level) {
  if(ocTree[node]) {
   if (ocTree[node].hidden) {
    return;
   }
   if(!materials[ocTree[node].material]) {
    log("Missing material "+ocTree[node].material+" for "+ node);
    return;
   }
   var m=document.getElementById('showMat'+ocTree[node].material);
   if(m && !m.checked) {
    return;
   }
  }
  var len=Math.pow(2,level);
  var len2=Math.pow(2,level-1);
  for(var xi=0;xi<2;xi++) {
   for(var yi=0;yi<2;yi++) {
    for(var zi=0;zi<2;zi++) {
     if (!ocTree[node]) {
      ocTree[node]={material:1};
     }
     ocTree[node].parent=node;
     var c=ocTree[node][rotColName(xi,yi,zi)];
     if (c) {
      drawTreeNode(c,x+len/2*xi,y+len/2*yi,z+len/2*zi,level-1);
     }
    }
   }
  }
  ctx.lineWidth=0.2;
  if(1==ocTree[node].material) { //air=transparent
   ctx.strokeStyle='#EEE';
   if (level==24) {
     ctx.lineWidth=2;
   } else {
     ctx.lineWidth=0.2;
   }
   //drawCube(x,y,z,len);
  } else {
   var isCursor=
    (x>=cursorPos[0]) && (x+len <= cursorPos[0]+levelLen) &&
    (y>=cursorPos[1]) && (y+len <= cursorPos[1]+levelLen) &&
    (z>=cursorPos[2]) && (z+len <= cursorPos[2]+levelLen);
   drawCube(x,y,z,len,materials[ocTree[node].material],isCursor);
  }
 }

 function drawTree() {
  drawTreeNode(root,-baseDiff,-baseDiff,-baseDiff,24);
 }

 function drawEarth() {
  ctx.lineWidth=2;
  ctx.strokeStyle='#666';
  drawCube(-baseDiff,-baseDiff,-baseDiff,2*baseDiff);
  ctx.strokeStyle='#ccc';
  ctx.lineWidth=0.4;
  drawCube(-baseDiff,-baseDiff,-baseDiff,baseDiff);
  drawBBox(-baseDiff,-baseDiff,-baseDiff,baseDiff,-baseDiff,-baseDiff);
  drawBBox(-baseDiff,-baseDiff,-baseDiff,-baseDiff,baseDiff,-baseDiff);
  drawBBox(-baseDiff,-baseDiff,0,-baseDiff,baseDiff,0);
  drawBBox(-baseDiff,-baseDiff,-baseDiff,-baseDiff,-baseDiff,baseDiff);
  drawBBox(0,0,-baseDiff,0,baseDiff,-baseDiff);
  drawCube(0,-baseDiff,-baseDiff,baseDiff);
  drawCube(-baseDiff,-baseDiff,0,baseDiff);
  drawCube(-baseDiff,-baseDiff,0,baseDiff);
  drawCube(0,0,-baseDiff,baseDiff);
  drawCube(-baseDiff,0,0,baseDiff);
  drawCube(0,0,0,baseDiff);
  drawCube(0,-baseDiff,-baseDiff,baseDiff);
  drawCube(0,0,0,baseDiff);
  ctx.fillStyle='#8080ff';
  ctx.beginPath();
  var rad=6300000.0;
  var radScale=80;
  ctx.moveTo(posX(0),posY(0));
  for (var i=0; i<360; i++) {
   ctx.moveTo(posX(i),posY(i));
  }
  //ctx.closePath();
  //ctx.stroke();
 }

 function nodeOfCursor(node,x,y,z,level) {
  level2=Math.pow(2,level-1);
  var xi=0;
  if (x>=level2) {
   xi=1;
   x-=level2;
  }
  var yi=0;
  if (y>=level2) {
   yi=1;
   y-=level2;
  }
  var zi=0;
  if (z>=level2) {
   zi=1;
   z-=level2;
  }
  var col=rotColName(xi,yi,zi);
  parentColumn=col;
  if(level==cursorLevel) {
   currNode=node;
   return;
  }
  var c= ocTree[node][col];
  currParent=node;
  if (c) {
   nodeOfCursor(c, x,y,z, level-1);
  } else {
   currNode=null;
  }
 }

 function keyHandler(event) {
  //log((event.shiftKey?"SH":"")+event.keyCode);
  var base=Math.pow(2,cursorLevel);
  if (event.keyCode==13) { //RET
   if(ocTree[currNode]) {
    ocTree[currNode].material=currMaterial;
    remoteSet();
    changed=true;
   } else {
    remoteAdd();
   }
  }
  //if (event.keyCode==32) { } //SPACE
  if (event.keyCode==37) { //left
    if (event.shiftKey) {
     cursorLevel--; //level down
     levelLen=Math.pow(2,cursorLevel);;
     var diff=Math.pow(2,cursorLevel);
     cursorPos[0]+=diff;
     cursorPos[1]+=diff;
     cursorPos[2]+=diff;
     draw();
    } else {
     if (cursorPos[1]> -Math.pow(2,23)) {
      cursorPos[1]-=base; //Y down
      draw();
     }
    }
  }
  if (event.keyCode==38) { //up
   if (event.shiftKey) {
    if (cursorPos[0]> -Math.pow(2,23)) {
     cursorPos[0]-=base; //X down
     draw();
    }
   } else {
    if (cursorPos[2]+base<Math.pow(2,23)) {
     cursorPos[2]+=base; //Z up
     draw();
    }
   }
  }
  if (event.keyCode==39) { //right
   if (event.shiftKey) { //level up
    if (cursorLevel<23) {
     cursorLevel++;
     levelLen=Math.pow(2,cursorLevel);
     cursorPos[0]= modulo(cursorPos[0],cursorLevel);
     cursorPos[1]= modulo(cursorPos[1],cursorLevel);
     cursorPos[2]= modulo(cursorPos[2],cursorLevel);
     //currNode=ocTree[currNode]['parent'];
     draw();
    }
   } else { //Y up
    if (cursorPos[1]+base<Math.pow(2,23)) {
     cursorPos[1]+=base;
     draw();
    }
   }
  }
  if (event.keyCode==40) { //down
   if (event.shiftKey) { //X up
    if (cursorPos[0]+base<Math.pow(2,23)) {
     cursorPos[0]+=base; 
     draw();
    }
   } else { //Z down
    if (cursorPos[2]> -Math.pow(2,23)) {
     cursorPos[2]-=base; 
     draw();
    }
   }
  }
  //if (event.keyCode==46) { } //DEL
  if (event.keyCode==82) { //'r'
   if (event.shiftKey) {
    rotZ=(rotZ+3)%4;
   } else {
    rotZ=(rotZ+1)%4;
   }
   draw();
  }
  if (event.keyCode==72) { //'h'
   var isHidden=ocTree[currNode].hidden;
   if (event.shiftKey) {
    for(var node in ocTree) {
     ocTree[node].hidden=false;
    }
   } else {
    ocTree[currNode].hidden=!isHidden;
   }
   draw();
  }
  if (event.keyCode==77) { //m
   recentMaterialsPos++;
   if(recentMaterialsPos>=recentMaterials.length) {
    recentMaterialsPos=0;
   }
   currMaterial=recentMaterials[recentMaterialsPos];
   setMaterial();
  }
  if (event.keyCode==187) { //'+'
   zoomLevel++;
   draw();
  }
  if (event.keyCode==189) { //'-'
   zoomLevel--;
   draw();
  }
 }

 function drawXYZ() {
  // see http://wiki.blender.org/index.php/Doc:2.4/Manual/3D_interaction/Transform_Control/Axis_Locking
  // X:
  var xOff=10;
  var yOff=10;
  ctx.fillStyle='red';
  ctx.strokeStyle='red';
  ctx.beginPath();
  ctx.moveTo(xOff+80,yOff+60);
  ctx.lineTo(xOff+70,yOff+70);
  ctx.stroke();
  ctx.fillText('x',xOff+65,yOff+70);
  // Y:
  ctx.fillStyle='green';
  ctx.strokeStyle='green';
  ctx.beginPath();
  ctx.moveTo(xOff+80,yOff+60);
  ctx.lineTo(xOff+100,yOff+60);
  ctx.stroke();
  ctx.fillText('y',xOff+100,yOff+55);
  // Z:
  ctx.fillStyle='blue';
  ctx.strokeStyle='blue';
  ctx.beginPath();
  ctx.moveTo(xOff+80,yOff+60);
  ctx.lineTo(xOff+80,yOff+40);
  ctx.stroke();
  ctx.fillText('z',xOff+83,yOff+50);
 }

 function pureIsoX(x,y,z) {
  return (y-x/2)/meterPerPixel*Math.pow(2,zoomLevel);
 }

 var xOff=270;
 function isoX(x,y,z) {
  return xOff+pureIsoX(x,y,z);
 }

 function pureIsoY(x,y,z) {
  return (x/2-z)/meterPerPixel*Math.pow(2,zoomLevel);
 }

 var yOff=250;
 function isoY(x,y,z) {
  return yOff+pureIsoY(x,y,z);
 }

 function drawBBox(xi,yi,zi,xo,yo,zo) {
  //top
  ctx.beginPath();
  ctx.moveTo(isoX(xo,yi,zo),isoY(xo,yi,zo));
  ctx.lineTo(isoX(xi,yi,zo),isoY(xi,yi,zo));
  ctx.lineTo(isoX(xi,yo,zo),isoY(xi,yo,zo));
  ctx.lineTo(isoX(xo,yo,zo),isoY(xo,yo,zo));
  ctx.closePath();
  ctx.stroke();
  //front
  ctx.beginPath();
  ctx.moveTo(isoX(xo,yi,zi),isoY(xo,yi,zi));
  ctx.lineTo(isoX(xo,yi,zo),isoY(xo,yi,zo));
  ctx.lineTo(isoX(xo,yo,zo),isoY(xo,yo,zo));
  ctx.lineTo(isoX(xo,yo,zi),isoY(xo,yo,zi));
  ctx.closePath();
  ctx.stroke();
  //right
  ctx.beginPath();
  ctx.moveTo(isoX(xo,yo,zo),isoY(xo,yo,zo));
  ctx.lineTo(isoX(xi,yo,zo),isoY(xi,yo,zo));
  ctx.lineTo(isoX(xi,yo,zi),isoY(xi,yo,zi));
  ctx.lineTo(isoX(xo,yo,zi),isoY(xo,yo,zi));
  ctx.closePath();
  ctx.stroke();
 }

 function drawCube(xi,yi,zi,len,fill,isCursor) {
  var x=isoX(xi,yi,zi);
  var y=isoY(xi,yi,zi);
  var l=len/meterPerPixel/2*Math.pow(2,zoomLevel);
  //top
  ctx.beginPath();
  ctx.moveTo(x-l,  y-l);
  ctx.lineTo(x,    y-2*l);
  ctx.lineTo(x+2*l,y-2*l);
  ctx.lineTo(x+l,y-l);
  ctx.closePath();
  var highlight=isCursor?30:0;
  ctx.stroke();
  if (fill) {
   ctx.fillStyle='rgb('+
    Math.max(0,fill.r-20+highlight)+','+
    Math.max(0,fill.g-20+highlight)+','+
    Math.max(0,fill.b-0+highlight)+')';
   ctx.fill();
  }
  //front
  ctx.beginPath();
  ctx.moveTo(x-l,y-l);
  ctx.lineTo(x+l,y-l);
  ctx.lineTo(x+l,y+l);
  ctx.lineTo(x-l,y+l);
  ctx.closePath();
  ctx.stroke();
  if (fill) {
   ctx.fillStyle='rgb('+
    Math.max(0,fill.r-0+highlight)+','+
    Math.max(0,fill.g-0+highlight)+','+
    Math.max(0,fill.b-0+highlight)+')';
   ctx.fill();
  }
  //right
  ctx.beginPath();
  ctx.moveTo(x+l,y-l);
  ctx.lineTo(x+2*l,y-2*l);
  ctx.lineTo(x+2*l,y);
  ctx.lineTo(x+l,y+l);
  ctx.closePath();
  ctx.stroke();
  if (fill) {
   ctx.fillStyle='rgb('+
    Math.max(0,fill.r-40+highlight)+','+
    Math.max(0,fill.g-30+highlight)+','+
    Math.max(0,fill.b-30+highlight)+')';
   ctx.fill();
  }
 }

 function addDiffTree(t) {
  var newCt=0;
  var updateCt=0;
  for(var cube in t) {
   if (ocTree[cube]) {
    updateCt++;
   } else {
    newCt++;
   }
   ocTree[cube]=t[cube];
  }
  log('added RecentCubes: '+ newCt + ' added, '+ updateCt+' updated');
 }

 function expandProperties() {
  addDiffTree(diffTree);
  addDiffTree(diffTree2);
  for(var node in ocTree) {
   ocTree[node].hidden=false;
   ocTree[node].material=ocTree[node].m;
   if( ocTree[node]['c']) {
    for( var i=0; i<8; i++) {
     if( ocTree[node]['c'][i]>0) {
      ocTree[node][childNames[i]]=ocTree[node]['c'][i];
     }
    }
   }
  }
 }
 expandProperties();

 function countChildren(node) {
  if(!ocTree[node]) {
   log("missing "+node);
   return;
  }
  ocTree[node].childCount=0;
  for(var i=0; i<8; i++) {
   var child=ocTree[node][childNames[i]];
   if (child) {
    ocTree[node].childCount++;
    ocTree[node].childCount+=countChildren(child);
   }
  }
  return ocTree[node].childCount;
 }
 countChildren(root);

 function findOrphanes() {
  for(var node in ocTree) {
   for(var i=0; i<8; i++) {
    var child=ocTree[node][childNames[i]];
    if (child) {
     if (ocTree[child]) {
      ocTree[child].parent=node;
     } else {
      log('*WARNING*: missing node: '+child);
     }
    }
   }
  }
  for(var node in ocTree) {
   if (! ocTree[node].parent && node != root) {
    log('*WARNING*: Orphan: '+node);
   }
  }
 }

 function drawCursorCube() {
  var len=Math.pow(2,cursorLevel);
  ctx.lineWidth=2;
  ctx.strokeStyle='#fff';
  drawCube(
   cursorPos[0], cursorPos[1], cursorPos[2], len);
  for(var i=0;i<23;i++) {
   if(cursorLevel<23-i) {
    ctx.lineWidth=2-i/5;
    ctx.strokeStyle='rgb('+(255-i*8)+','+(255-i*8)+','+(255-i*8)+')';
    drawCube(
     modulo(cursorPos[0],cursorLevel+i+1),
     modulo(cursorPos[1],cursorLevel+i+1),
     modulo(cursorPos[2],cursorLevel+i+1), len*Math.pow(2,i+1));
   }
  }
 }

 function drawCursor() {
  var len=Math.pow(2,cursorLevel);
  var lenS=(len<1000)?len+' m':(len/1000).toFixed(2)+' km';
  document.getElementById('size').innerHTML='2^'+cursorLevel+' m = '+lenS;
  ctx.strokeStyle='#888';
  ctx.lineWidth=1;
  ctx.strokeStyle='#f00';
  drawBBox(
   -baseDiff, cursorPos[1], cursorPos[2],
    baseDiff, cursorPos[1]+len, cursorPos[2]+len);
  ctx.strokeStyle='#0f0';
  drawBBox(
   cursorPos[0],    -baseDiff, cursorPos[2],
   cursorPos[0]+len, baseDiff, cursorPos[2]+len);
  ctx.strokeStyle='#00f';
  drawBBox(
   cursorPos[0],     cursorPos[1],    -baseDiff,
   cursorPos[0]+len, cursorPos[1]+len, baseDiff);
  drawCursorCube();
  var i=document.getElementById('info');
  i.innerHTML='['+cursorPos[0]+','+cursorPos[1]+','+cursorPos[2]+'] to';
  i=document.getElementById('infoTo');
  i.innerHTML='&nbsp;['+(cursorPos[0]+len)+','+(cursorPos[1]+len)+','+(cursorPos[2]+len)+']';
  document.getElementById('cubeCount').innerHTML=Object.keys(ocTree).length;
  document.getElementById('node').innerHTML=currNode?currNode:'*undefined*';
  document.getElementById('parent').innerHTML=currParent+' (as '+parentColumn+')';
  var cct=0;
  if (currNode) {
   document.getElementById('material').innerHTML=materials[ocTree[currNode]['material']]['name'];
   for(var i=0;i<8;i++) {
    if (ocTree[currNode][childNames[i]]) {
     cct++
    }
   }
   document.getElementById('allChildCount').innerHTML=ocTree[currNode].childCount;
  }
  document.getElementById('childCount').innerHTML=cct;
  drawInfo();
 }

 //const
 var a = 6378137;
 //const
 var e = 8.1819190842622e-2;
 var esq = Math.pow(e,2);

 //https://gist.github.com/klucar/1536194
 function llaToEcef(lat,lon,alt) {
  var N = a / Math.sqrt(1 - esq * Math.pow(Math.sin(lat),2));
  var x = (N+alt) * Math.cos(lat) * Math.cos(lon);
  var y = (N+alt) * Math.cos(lat) * Math.sin(lon);
  var z = ((1-esq) * N + alt) * Math.sin(lat);
  return [x, y, z];
 }

 function ecefToLla(x,y,z) {
  // via https://gist.github.com/klucar/1536194 and
  // http://www.gal-systems.com/2011/09/convert-coordinates-from-ecef-to.html :
  var b = Math.sqrt(Math.pow(a, 2) * (1 - Math.pow(e, 2)));
  var ep = Math.sqrt((Math.pow(a, 2) - Math.pow(b, 2)) / Math.pow(b, 2));
  var p = Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2));
  var th = Math.atan2(a * z, b * p);
  var lon = Math.atan2(y, x);
  var lat = Math.atan2((z + Math.pow(ep, 2) * b * Math.pow(Math.sin(th), 3)),
         (p - Math.pow(e, 2) * a * Math.pow(Math.cos(th), 3)));
  var N = a / (Math.sqrt(1 - Math.pow(e, 2) * Math.pow(Math.sin(lat), 2)));
  var alt = p / Math.cos(lat) - N;

  lon = lon % (2 * Math.PI);

  if ( Math.abs(x) < 1.0 && Math.abs(y) < 1.0) {
   alt = Math.abs(z) - b;
  }

  lat = lat * 180 / Math.PI;
  lon = lon * 180 / Math.PI + SingularMeridian-rotZ*90;
  return [lat, lon, alt];
 }

 function drawInfo() {
  var center=Math.pow(2,cursorLevel-1);
  var x=cursorPos[0]+center;
  var y=cursorPos[1]+center;
  var z=cursorPos[2]+center;
  var ecef=ecefToLla(x,y,z);
  var lat=ecef[0];
  var lon=ecef[1];
  var alt=ecef[2];
  var latS=Math.abs(lat).toFixed(2)+'&deg;'+((lat<0)?'S':'N');
  var lonS=Math.abs(lon).toFixed(2)+'&deg;'+((lon<0)?'W':'E');
  var altS;
  if (Math.abs(alt)<1000) {
   altS=Math.abs(alt).toFixed(2)+' m';
  } else {
   altS=(Math.abs(alt)/1000).toFixed(2)+' km';
  }
  // http://wiki.openstreetmap.org/wiki/Static_map_images
  var imgBase='http://pafciu17.dev.openstreetmap.org/?module=map&width=260&height=250&';
  imgBase+='&zoom='+(24-cursorLevel);
  imgBase+='&lat='+lat;
  imgBase+='&lon='+lon;
  document.getElementById('img').src=imgBase;
  document.getElementById('pos').innerHTML=latS+' '+lonS+' '+((alt<0)?'-':'+')+altS;
  document.getElementById('spinner').style.zIndex=2;
  document.getElementById('osm').href='https://www.openstreetmap.org/?'+
   'mlat='+lat+'&'+
   'mlon='+lon+'&'+
   'zoom='+Math.min(18,(24-cursorLevel));
 }

 var boxSize=document.getElementById('xBox').width;

 // https://en.wikipedia.org/wiki/Earth_radius
 var rEarth=6371000.8; // ToDo: add ellipsoid

 function drawCutArc(box,dist,p1,p2) {
  // r^2+dist^2=rEarth^2
  var dDist=rEarth*rEarth-Math.pow(dist,2);
  // center relative to 50/50 and levelLen=80px
  if (dDist>0) {
   box.beginPath();
   var r=Math.sqrt(dDist)*(boxSize-20)/levelLen;
   box.arc(
    boxSize/2+(boxSize-20)*(p1+levelLen/2)/levelLen,
    boxSize/2+(boxSize-20)*(p2+levelLen/2)/levelLen,
    r,0,2*Math.PI);
   box.fill();
   box.strokeStyle='white';
   box.stroke();
  }
 }

 // how is the current cube cut by PlanetEarth?:
 function drawCutCircle(box,pos,p1,p2) {
  box.fillStyle='#000';
  box.fillRect(0,0,boxSize,boxSize);

  box.lineWidth=1;
  var sort=[
   {d:0,'c':'rgb(116,90,60)'},
   {d:Math.abs(pos),'c':'rgb(156,90,60)'},
   {d:Math.abs(pos+levelLen), 'c':'rgb(196,90,60)'}];
  sort.sort(function(a,b){return a['d']-b['d']});
  for( var i=0; i<3; i++) {
   box.fillStyle=sort[i]['c'];
   drawCutArc(box,sort[i]['d'], p1,p2);
  }
  box.strokeStyle='#fff';
  box.strokeRect(10,10,boxSize-20,boxSize-20);
 }

 var osmLoading=true;

 function osmLoaded() {
  document.getElementById('spinner').style.zIndex=-1;
 }

 function draw() {
  nodeOfCursor(root,
   cursorPos[0]+baseDiff,
   cursorPos[1]+baseDiff,
   cursorPos[2]+baseDiff,24);
  xOff=pane.width/2-pureIsoX(cursorPos[0],cursorPos[1],cursorPos[2]);
  yOff=pane.height/2-pureIsoY(cursorPos[0],cursorPos[1],cursorPos[2]);
  //main pane
  ctx.fillStyle='#000';
  ctx.fillRect(0,0,pane.width,pane.height);
  ctx.fillStyle='#444';
  ctx.font="160px Arial";
  ctx.fillText('Digital',110,150);
  ctx.fillText('Planet',200,450);
  ctx.font="16px Arial";

  //lower control pane:
  ctx.fillStyle='#aaa';
  //ctx.fillRect(2,302,230,16);

  drawCutCircle(xBox,cursorPos[0],cursorPos[1],cursorPos[2]);
  var box=xBox;
  box.font="16px Arial";
  box.lineWidth=2;

  box.fillStyle='green';
  box.strokeStyle='green';
  box.beginPath();
  box.moveTo(40,40);
  box.lineTo(60,40);
  box.stroke();
  box.fillText('y',55,55);
  box.fillStyle='blue';
  box.strokeStyle='blue';
  box.beginPath();
  box.moveTo(40,40);
  box.lineTo(40,20);
  box.stroke();
  box.fillText('z',45,30);

  drawCutCircle(yBox,cursorPos[1],cursorPos[0],cursorPos[2]);
  box=yBox;
  box.font="16px Arial";
  box.lineWidth=2;
  box.fillStyle='red';
  box.strokeStyle='red';
  box.beginPath();
  box.moveTo(40,40);
  box.lineTo(20,40);
  box.stroke();
  box.fillText('x',20,55);
  box.fillStyle='blue';
  box.strokeStyle='blue';
  box.beginPath();
  box.moveTo(40,40);
  box.lineTo(40,20);
  box.stroke();
  box.fillText('z',45,30);

  drawCutCircle(zBox,cursorPos[2],cursorPos[1],cursorPos[0]);
  box=zBox;
  box.font="16px Arial";
  box.fillStyle='green';
  box.strokeStyle='green';
  box.lineWidth=2;
  box.beginPath();
  box.moveTo(40,40);
  box.lineTo(60,40);
  box.stroke();
  box.fillText('y',60,55);
  box.fillStyle='red';
  box.strokeStyle='red';
  box.beginPath();
  box.moveTo(40,40);
  box.lineTo(40,60);
  box.stroke();
  box.fillText('x',45,65);

  drawEarth();
  drawTree();
  drawCursor();
  drawXYZ();
 }

 draw();

 document.onkeydown=keyHandler;

 findOrphanes();

 //ToDo

 // based on http://sl4.eu/wiki/SimplifiedLandPolygons plus PyShp:
 var shape=[
  [-221314.17945856444, 6565234.738303548],
  [-221457.3697195735, 6565590.933818393],
  [-220555.225434235, 6565682.084675092],
  [-220725.98953311297, 6565184.931190011],
  [-221314.17945856444, 6565234.738303548]];

 shape=[
  [-526864.129294976, 7464424.244210574],
  [-527244.1740365429, 7464540.668494733],
  [-527482.6203858217, 7465038.441399676],
  [-526979.0110094729, 7465000.679550971],
  [-526864.129294976, 7464424.244210574]];

 function mercatorToWgs(x,y) {
  //based on http://www.gal-systems.com/2011/07/convert-coordinates-between-web.html
  var num3 = x / 6378137.0;
  var num4 = num3 * 57.295779513082323;
  var num5 = Math.floor((num4 + 180.0) / 360.0);
  var lon = num4 - (num5 * 360.0);
  var num7 = 1.5707963267948966 - (2.0 * Math.atan(Math.exp((-1.0 * y) / 6378137.0)));
  lat = num7 * 57.295779513082323;
  return [lon,lat];
 }

 var ret="";
 for(var i=0;i<shape.length;i++) {
  ret+=mercatorToWgs(shape[i][0],shape[i][1])+"\n";
 }
 //alert(ret);

 function posX(deg) {
  return Math.sin(deg*Math.PI/180.0);   
 }

 function posY(deg) {
  return Math.cos(deg*Math.PI/180.0);
 }

 function toggleMenu(b) {
  id=b.id.substring(3);
  var t=document.getElementById('content'+id).style;
  if ('block'==t.display) {
   b.innerHTML='+';
   t.display='none';
  } else {
   b.innerHTML='-';
   t.display='block';
  }
 }

 // 
 // currently unused:
 //
 function click(event) {
 //http://stackoverflow.com/questions/9880279/how-do-i-add-a-simple-onclick-event-handler-to-a-canvas-element
  var x = event.pageX - pane.offsetLeft;
  var y = event.pageY - pane.offsetTop;
  if (x>0 && y>0) {
   log("click: "+x+" "+y);
  }
 }
pane.addEventListener('click',click,false);

 //initMaterials()
 for(var m in materials) {
  var col='rgb('+
   materials[m].r+','+
   materials[m].g+','+
   materials[m].b+')';
  document.getElementById('matName'+m).innerHTML=materials[m].name;
  document.getElementById('matColor'+m).style.backgroundColor=col;
  if('air'!=materials[m].name) {
   document.getElementById('showMatName'+m).innerHTML=materials[m].name;
   document.getElementById('showMatColor'+m).style.backgroundColor=col;
  }
 }

/*Point = function(lat,lon,opt_alt) {
  this.lat=lat;
  this.lon=lat;
  this.alt=opt_alt;
 }*/